package com.xiaouyudeguang.common.utils;

import groovy.lang.GroovyClassLoader;
import groovy.lang.GroovyObject;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.Map;

@Slf4j
public class GroovyUtils {

    public static final String DEFAULT_FUNCTION = "def %s(Map<String, Object> param)";

    public static final String DEFAULT_FUNCTION_NAME = "default_function_name";

    private static final String defaultFuncName = System.getProperty(DEFAULT_FUNCTION_NAME, "func");

    public static Object exc(String source, Object[] param) throws IOException {
        return exc(source, defaultFuncName, param);
    }

    public static Object exc(String source, String funcName, Object[] param) throws IOException {
        try (GroovyClassLoader classLoader = new GroovyClassLoader()) {
            if (source.endsWith(".groovy")) {
                source = FileUtils.getResource(source);
            }
            if (source == null || !source.contains("return")) {
                return null;
            }
            String functionDef = String.format(DEFAULT_FUNCTION, funcName);
            if (!source.contains(functionDef)) {
                source = functionDef + " { " + source + " }";
            }
            Class<?> groovyClass = classLoader.parseClass(source.replace("$", "\\$"));
            GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
            return groovyObject.invokeMethod(funcName, param);
        } catch (Exception e) {
            log.error(e.getMessage());
            return source;
        }
    }

    public static Object exc(String source, Map<String, Object> param) throws IOException {
        return exc(source, defaultFuncName, param);
    }

    public static Object exc(String source, String funcName, Map<String, Object> param) throws IOException {
        try (GroovyClassLoader classLoader = new GroovyClassLoader()) {
            if (source.endsWith(".groovy")) {
                source = FileUtils.getResource(source);
            }
            if (source == null || !source.contains("return")) {
                return null;
            }
            String functionDef = String.format(DEFAULT_FUNCTION, funcName);
            if (!source.contains(functionDef)) {
                source = functionDef + " { " + source + " }";
            }
            Class<?> groovyClass = classLoader.parseClass(source.replace("$", "\\$"));
            GroovyObject groovyObject = (GroovyObject) groovyClass.newInstance();
            return groovyObject.invokeMethod(funcName, param);
        } catch (Exception e) {
            log.error(e.getMessage());
            return source;
        }
    }
}
